#include "tcp_server.hpp"
#include <functional>
#include "../base/logger.h"
#include "tcp_connection.hpp"

namespace easyasio {
namespace net {

TcpServer::TcpServer(const std::string& address, const std::string& port, std::size_t io_service_pool_size)
  : io_service_pool_(io_service_pool_size, true),
    signals_(io_service_pool_.get_io_service()),
    acceptor_(io_service_pool_.get_io_service()),
    new_connection_()
{
	signals_.add(SIGINT);
	signals_.add(SIGTERM);
#if defined(SIGQUIT)
	signals_.add(SIGQUIT);
#endif // defined(SIGQUIT)
	signals_.async_wait(std::bind(&TcpServer::handle_stop, this));

	asio::ip::tcp::resolver resolver(acceptor_.get_io_service());
	asio::ip::tcp::resolver::query query(address, port);
	asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
	acceptor_.open(endpoint.protocol());
	acceptor_.set_option(asio::ip::tcp::acceptor::reuse_address(true));
	acceptor_.bind(endpoint);
	acceptor_.listen();
}

void TcpServer::run()
{
	start_accept();
	io_service_pool_.run();
}

void TcpServer::start_accept()
{
	new_connection_.reset(new TcpConnection(io_service_pool_.get_io_service()));
	new_connection_->setConnectionCallback(connectionCallback_);
	new_connection_->setMessageCallback(messageCallback_);
	new_connection_->setWriteCompleteCallback(writeCompleteCallback_);
    new_connection_->setCloseCallback(closeCallback_);
	acceptor_.async_accept(
        new_connection_->socket(), std::bind(&TcpServer::handle_accept, this, std::placeholders::_1));
}

void TcpServer::handle_accept(const asio::error_code& e)
{
    if (!e)
    {
        new_connection_->start();
    }
    else
    {
        LOG_WARN("server::handle_accept, error {}", e.message());
    }

	start_accept();
}

void TcpServer::handle_stop()
{
    LOG_TRACE("server::handle_stop");
	io_service_pool_.stop();
}

} // namespace net  
} // namespace easyasio  
